package com.pactera.asmp.server.service;

import java.time.LocalDateTime;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.pactera.asmp.server.common.constants.ResultCode;
import com.pactera.asmp.server.common.exception.CustomException;
import com.pactera.asmp.server.dao.ConstantInfoMapper;
import com.pactera.asmp.server.dao.ScriptInfoMapper;
import com.pactera.asmp.server.entity.ConstantInfoDTO;
import com.pactera.asmp.server.entity.ConstantInfoSearchDTO;
import com.pactera.asmp.server.pojo.ConstantInfo;
import com.pactera.asmp.server.pojo.ScriptInfo2;
import com.pactera.asmp.server.pojo.User;
import com.pactera.asmp.server.utils.AssertUtil;
import com.pactera.asmp.server.utils.PageDataResult;

@Service
public class ConstantInfoServiceImpl implements IConstantInfoService {

    private static final Logger logger = LoggerFactory.getLogger(ConstantInfoServiceImpl.class);

    @Autowired
    private ConstantInfoMapper constantInfoMapper;
    @Autowired
    private IConstantInfoHistoryService constantInfoHistoryService;
    @Autowired
    private ScriptInfoMapper scriptInfoMapper;
//    @Autowired
//    private ProjectModuleMapper projectModuleMapper;
    @Autowired
    private UserService userService;

    @Override
    public PageDataResult select(ConstantInfoSearchDTO constantInfoSearchDTO) {
        logger.info(JSONObject.toJSONString(constantInfoSearchDTO));
        constantInfoSearchDTO.setProjectIds(userService.getRelatedProject());
        PageDataResult pageDataResult = new PageDataResult();
        PageHelper.startPage(constantInfoSearchDTO.getPage(), constantInfoSearchDTO.getLimit());
        constantInfoSearchDTO.setStatus(1);
        List<ConstantInfo> list = constantInfoMapper.select(constantInfoSearchDTO);
        PageInfo<ConstantInfo> pageInfo = new PageInfo<>(list);
        pageDataResult.setTotals(Long.valueOf(pageInfo.getTotal()).intValue());
        pageDataResult.setList(list);
        return pageDataResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<Long> datas) {
        logger.info(JSONObject.toJSONString(datas));

//        List<ConstantInfo> constantInfos = constantInfoMapper.selectByIds(datas);
//        if(constantInfos.stream().anyMatch(constantInfo -> constantInfo.getServiceStatus().intValue() == 1)) {
//            throw new CustomException(ResultCode.PARAM_IN_USED);
//        }
        for (Long id : datas) {
            ConstantInfo constantInfo = this.getConstantByPrimaryKey(id);
            constantInfoHistoryService.insert(constantInfo, 3);
            constantInfoMapper.deleteScriptAndConstantRel(null, id);
        }
        return constantInfoMapper.deleteByPrimaryKeys(datas, LocalDateTime.now())>0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ConstantInfoDTO insert(ConstantInfoDTO constantInfoDTO) {
        logger.info(JSONObject.toJSONString(constantInfoDTO));
        AssertUtil.notNull(constantInfoDTO,"参数异常");

        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);

        if(!checkNameExist(null, constantInfoDTO.getName(), constantInfoDTO.getProjectId()))
            throw new CustomException(ResultCode.BUSINESS_CONSTANTNAME_EXISTED);
        constantInfoDTO.setUserId((long)currUser.getId());
        if(!CollectionUtils.isEmpty(constantInfoDTO.getScrpitIds())) constantInfoDTO.setServiceStatus(1);
        constantInfoDTO.setTimeCreate(LocalDateTime.now());
        constantInfoMapper.insert(constantInfoDTO);
        if(!CollectionUtils.isEmpty(constantInfoDTO.getScrpitIds())) {
            for(Long scriptId:constantInfoDTO.getScrpitIds()) {
                constantInfoMapper.insertScriptAndConstantRel(scriptId, constantInfoDTO.getId());
            }
        }
        ConstantInfo constantInfo = new ConstantInfo();
        BeanUtils.copyProperties(constantInfoDTO, constantInfo);
        constantInfoHistoryService.insert(constantInfo, 1);
        return constantInfoDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(ConstantInfo constantInfo) {
        logger.info(JSONObject.toJSONString(constantInfo));
        User currUser = (User) SecurityUtils.getSubject().getPrincipal();
        if (currUser == null) throw new CustomException(ResultCode.PERMISSION_EXPIRE);

        if(!checkNameExist(constantInfo.getId(), constantInfo.getName(), constantInfo.getProjectId()))
            throw new CustomException(ResultCode.BUSINESS_CONSTANTNAME_EXISTED);

        constantInfo.setUpdateUserId((long)currUser.getId());
        // 更新前获取旧数据，并添加到历史记录表
        ConstantInfo constantInfoOld = this.getConstantByPrimaryKey(constantInfo.getId());
        constantInfoHistoryService.insert(constantInfoOld, 2);

        constantInfoMapper.deleteScriptAndConstantRel(null, constantInfo.getId());
        if(!CollectionUtils.isEmpty(constantInfo.getScrpitIds())) {
            for(Long scriptId:constantInfo.getScrpitIds()) {
                constantInfoMapper.insertScriptAndConstantRel(scriptId, constantInfo.getId());
            }
            constantInfo.setServiceStatus(1);
        }else {
            constantInfo.setServiceStatus(0);
        }
        return constantInfoMapper.update(constantInfo) > 0;
    }

    private ConstantInfo getConstantByPrimaryKey(Long id) {
        ConstantInfoSearchDTO constantInfoSearchDTO = new ConstantInfoSearchDTO();
        constantInfoSearchDTO.setId(id);
        constantInfoSearchDTO.setStatus(1);
        List<ConstantInfo> list = constantInfoMapper.select(constantInfoSearchDTO);
        if (CollectionUtils.isEmpty(list)) {
            throw new CustomException(ResultCode.BUSINESS_CONSTANT_NOT_EXISTED);
        }
        return list.get(0);
    }

    @Override
    public List<ScriptInfo2> selectRelScpritList(Long constantId) {
        logger.info(String.valueOf(constantId));
        if (null == constantId || 0 == constantId) {
            throw new CustomException(ResultCode.PARAM_IS_BLANK);
        }
        List<Integer> scriptIds = constantInfoMapper.selectScriptIdsByConstantId(constantId);
        if(CollectionUtils.isEmpty(scriptIds)) {
            return Lists.newArrayList();
        }
        return scriptInfoMapper.selectScriptByScriptIds(scriptIds);
    }

    @Override
    public int updateConstantServiceStatus(List<Long> datas, Integer serviceStatus) {
        logger.info(JSONObject.toJSONString(datas), serviceStatus);
        if(CollectionUtils.isEmpty(datas)) {
            return 0;
        }
        return constantInfoMapper.updateConstantServiceStatus(datas, serviceStatus);
    }

    private boolean checkNameExist(Long id, String name, Integer projectId) {
        ConstantInfo constantInfo = constantInfoMapper.selectByNameAndProjectId(name, projectId);
        if(null == constantInfo || null == constantInfo.getId()) {
            return true;
        }
        if(null == id) {
            return false;
        }
        return id.longValue() == constantInfo.getId().longValue();
    }
}
